/**
 * 
 */
package persistence;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.digester.Digester;
import org.xml.sax.SAXException;

/**
 * @author fabiensaulnier
 * 
 */
public class PersistenceConfiguration {

	/**
	 * Une List de PersistentClass
	 */
	private List<PersistentClass> persistentClasses = new ArrayList<PersistentClass>();

	/**
	 * Contient les paramètres de la connexion à la BD (driverClass, url,
	 * userName, password)
	 */
	private ConnectionConfiguration connectionConfiguration;

	/**
	 * Constructeur par défaut
	 */
	public PersistenceConfiguration() {
	}

	/**
	 * Constructeur
	 * 
	 * @param fileName
	 * @throws PersistenceException
	 */
	public PersistenceConfiguration(String fileName) throws PersistenceException {
		this.parseConfigFile(fileName);
		PersistenceUtil.setPersistenceConfiguration(this);
	}

	private void parseConfigFile(String fileName) throws PersistenceException {

		Digester digester = new Digester();
		digester.setValidating(false);
		digester.push(this);
		digester.addObjectCreate("persistence-configuration/connection", ConnectionConfiguration.class);
		digester.addBeanPropertySetter("persistence-configuration/connection/driver-class", "driverClass");
		digester.addBeanPropertySetter("persistence-configuration/connection/url", "url");
		digester.addBeanPropertySetter("persistence-configuration/connection/username", "userName");
		digester.addBeanPropertySetter("persistence-configuration/connection/password", "password");

		digester.addObjectCreate("persistence-configuration/connection/c3p0", C3p0Configuration.class);
		digester.addBeanPropertySetter("persistence-configuration/connection/c3p0/min-size", "minSize");
		digester.addBeanPropertySetter("persistence-configuration/connection/c3p0/max-size", "maxSize");
		digester.addBeanPropertySetter("persistence-configuration/connection/c3p0/timeout", "timeout");
		digester.addBeanPropertySetter("persistence-configuration/connection/c3p0/max-statements", "maxStatements");
		digester.addSetNext("persistence-configuration/connection/c3p0", "addC3p0Configuration");

		digester.addSetNext("persistence-configuration/connection", "addConnectionConfiguration");

		digester.addObjectCreate("persistence-configuration/mapped-classes/mapped-class", PersistentClass.class);
		digester.addSetProperties("persistence-configuration/mapped-classes/mapped-class", "name", "name");
		digester.addSetNext("persistence-configuration/mapped-classes/mapped-class", "addPersistentClass");

		InputStream s = getClass().getClassLoader().getResourceAsStream(fileName);
		if (s == null) {
			throw new PersistenceException("Persistence configuration file not found ");
		}
		try {
			digester.parse(s);
		} catch (IOException e) {
			throw new PersistenceException("Exception while parsing config file :" + e.getMessage());
		} catch (SAXException e) {
			throw new PersistenceException("Exception while parsing config file :" + e.getMessage());
		}
	}

	public void addConnectionConfiguration(ConnectionConfiguration connectionConfiguration) {
		this.connectionConfiguration = connectionConfiguration;
	}

	public void addPersistentClass(PersistentClass persistentClass) throws PersistenceException {
		persistentClass.parse();
		if (!this.persistentClasses.contains(persistentClass))
			this.persistentClasses.add(persistentClass);
	}

	/**
	 * @return the persistentClasses
	 */
	public List<PersistentClass> getPersistentClasses() {
		return persistentClasses;
	}

	/**
	 * @return the connectionConfiguration
	 */
	public ConnectionConfiguration getConnectionConfiguration() {
		return connectionConfiguration;
	}

	/**
	 * 
	 * @param clazz
	 * @return
	 * @throws PersistenceException
	 */
	public PersistentClass getPersistentClass(Class<?> clazz) throws PersistenceException {
		for (PersistentClass persistentClass : this.persistentClasses) {
			if (persistentClass.getName().equalsIgnoreCase(clazz.getName()) || persistentClass.getName().equals(clazz.getSuperclass().getName())) {
				return persistentClass;
			}
		}
		throw new PersistenceException("Impossible de trouver la classe : " + clazz.getName());
	}

	/**
	 * Retourne la sessionFactory
	 * 
	 * @return
	 */
	public PersistenceSessionFactory getPersistenceSessionFactory() {
		PersistenceSessionFactory persistenceSessionFactory = new PersistenceSessionFactory(this);
		return persistenceSessionFactory;
	}

}
